package com.liuhouse.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.liuhouse.constants.SystemCanstants;
import com.liuhouse.domain.LoginUser;
import com.liuhouse.enums.AppHttpCodeEnum;
import com.liuhouse.exception.SystemException;
import com.liuhouse.pojo.Comment;
import com.liuhouse.mapper.CommentMapper;
import com.liuhouse.pojo.User;
import com.liuhouse.service.ICommentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liuhouse.service.IUserService;
import com.liuhouse.utils.BeanCopyUtils;
import com.liuhouse.utils.RedisCache;
import com.liuhouse.utils.ResponseResult;
import com.liuhouse.utils.SecurityUtils;
import com.liuhouse.vo.CommentVo;
import com.liuhouse.vo.PageVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.List;

/**
 * <p>
 * 评论表 服务实现类
 * </p>
 *
 * @author liuhouse
 * @since 2024-01-27
 */
@Service
public class CommentServiceImpl extends ServiceImpl<CommentMapper, Comment> implements ICommentService {


    @Autowired
    private IUserService userService;

    @Autowired
    private RedisCache redisCache;

    /**
     * 获取文章的评论信息
     * @param articleId
     * @param pageNum
     * @param pageSize
     * @return
     */
    @Override
    public ResponseResult commentList(String commentType, Long articleId, Integer pageNum, Integer pageSize) {
        //根据articleId获取对应的文章评论信息
        //构建查询条件
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        //得到当前文章所有的评论
        //对articleId进行判断,作用是得到指定文章,如果是文章评论,才会判断articleId,避免友情链接判断articleID时出现空指针
         queryWrapper.eq(SystemCanstants.ARTICLE_COMMENT.equals(commentType) , Comment::getArticleId , articleId);
        //对评论区的某条评论进行rootId进行判断,如果为-1，就表示根评论，SystemCanstants.COMMENT_ROOT 就是我们自己写的常量
        queryWrapper.eq(Comment::getRootId , SystemCanstants.COMMENT_ROOT);
        //根据现在查询的类型,去查询到底是文章评论还是友情链接的评论
        queryWrapper.eq(Comment::getType , commentType);
        //分页查询,查询的是整个评论区的每一条评论
        Page<Comment> page = new Page<>(pageNum, pageSize);
        this.page(page , queryWrapper);
        //调用下面的方法 对分页评论数据进行转换
        List<CommentVo> commentVoList = comentToCommentVoList(page.getRecords());
        //遍历,可以使用for循环,也可以使用stream流,查询子评论(注意子评论只查找到二级评论,不再往深查)
        for(CommentVo commentVo : commentVoList){
            //查询对应的子评论
            List<CommentVo> children = getChildren(commentVo.getId());
            //把查询到的children子评论的集合,赋值给commentVo的children字段
            commentVo.setChildren(children);
        }

        return ResponseResult.okResult(new PageVo(commentVoList , page.getTotal()));
    }

    //在文章的评论区域发送评论
    @Override
    public ResponseResult addComment(Comment comment) {
        //注意前端在调用这个发送评论的接口的时候,在请求体中没有向我们传入 createTime , createBy , updateTime , updateBy
        //我们这里在往后端插入数据的时候 就会导致上面的那四个字段没有值
        //为了解决这个问题,我们在liuhouse-framework工程中新增了 MyMetaObjectHandler类，修改了Comment类,详细可以自己定位过去看一下代码
        //如果没有登录,不允许评论


        if(!StringUtils.hasText(comment.getContent())){
            throw new SystemException(AppHttpCodeEnum.CONTENT_NOT_NULL);
        }
        save(comment);
        return ResponseResult.okResult();
    }

    //根据评论id，来查询对应的所有子评论(注意只查找到二级评论,不再往深查询)
    private List<CommentVo> getChildren(Long id) {
        LambdaQueryWrapper<Comment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Comment::getRootId , id);
        //对子评论进行时间排序
        queryWrapper.orderByAsc(Comment::getCreateTime);
        //查找子评论
        List<Comment> comments = list(queryWrapper);
        //进行comments 转换 成 commentVO11
        List<CommentVo> commentVos = comentToCommentVoList(comments);
        return commentVos;
    }

    private List<CommentVo> comentToCommentVoList(List<Comment> list) {
        //对评论区所有的评论进行转换
        List<CommentVo> commentVos = BeanCopyUtils.copyBeanList(list, CommentVo.class);
        //遍历。由于封装响应好的数据里面没有username字段,所以我们还不能返回给前端,这个遍历就是用来得到username字段
        String nickName = "游客用户";
        for(CommentVo commentVo : commentVos){
            //需要根据commentVo类里面的createBy字段去查找user表中的nickName字段
            User user = userService.getById(commentVo.getCreateBy());
           if(user != null){
               nickName = user.getNickName();
           }
            //然后把nickname字段(发这条子评论的用户昵称)的数据赋值给commentVo类的username字段
            commentVo.setUsername(nickName);

            //查询评论的用户昵称,怎么判断是评论的用户呢,判断getToCommentUserId为-1,就表示这条评论是根评论
            //那么就不是回复的，这个字段就不需要  如果说大于-1，就代表这个是回复给别人的，就要显示出来
            if(commentVo.getToCommentUserId() != -1){
                //获取给回复人的名称
                String toCommentUserName = userService.getById(commentVo.getToCommentUserId()).getNickName();
                //然后把nickname字段(发这条评论的用户昵称)数据赋值给commentVo类的toCommentUserName字段
                commentVo.setToCommentUserName(toCommentUserName);
            }
        }
        return commentVos;
    }
}
